package com.pansoft.openplanet.activity;

import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.AnimationDrawable;
import android.os.Bundle;
import androidx.core.content.ContextCompat;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

import com.efounder.chat.struct.StructFactory;
import com.efounder.constant.EnvironmentVariable;
import com.efounder.frame.utils.Constants;
import com.efounder.message.manager.JFMessageManager;
import com.efounder.message.struct.IMStruct002;
import com.efounder.util.EnvSupportManager;
import com.efounder.utils.ResStringUtil;
import com.pansoft.nfc.mifare.Common;
import com.pansoft.nfc.mifare.activity.MifareNfcMessageActivity;
import com.pansoft.openplanet.R;
import com.pansoft.openplanet.account.util.EosAccountGenerator;
import com.pansoft.openplanet.bean.Account;
import com.pansoft.openplanet.bean.AssetListBean;
import com.pansoft.openplanet.blockchain.api.EosChainInfo;
import com.pansoft.openplanet.blockchain.chain.SignedTransaction;
import com.pansoft.openplanet.blockchain.types.TypeChainId;
import com.pansoft.openplanet.constant.IPAssetsConstant;
import com.pansoft.openplanet.db.AccountDao;
import com.pansoft.openplanet.util.BalanceUtil;
import com.pansoft.openplanet.util.EosNetParamUtil;
import com.pansoft.openplanet.util.EthTokenTransactionManager;
import com.pansoft.openplanet.util.TCAccountManager;
import com.pansoft.openplanet.util.UTXOTransactionManager;
import com.pansoft.openplanet.widget.TCLoadingDataView;
import com.utilcode.util.LogUtils;
import com.utilcode.util.StringUtils;

import net.sf.json.JSONObject;

import org.bitcoinj.core.Coin;
import org.bitcoinj.core.Transaction;
import org.web3j.crypto.Credentials;
import org.web3j.tx.Contract;
import org.web3j.utils.Convert;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;

import static com.efounder.frame.utils.Constants.CHAT_USER_ID;
import static com.pansoft.openplanet.fragment.BottomTransferConfirmDialogFragment.REQUEST_READ_NFC_PRIV_KEY;

/**
 * 转账成功
 * Created by will on 18-3-26.
 */

public class ChatTransferSuccessActivity extends TCBaseActivity {

    private static final String TAG = "TransferSuccessActivity";

    private TextView tvCode, tvCodeIntro, tvMyAddressIntro, tvMyAddress,
            tvToAddressIntro, tvToAddress, tvCount, tvCountUnit, tvTransStatus, tvTitle;
    private ImageView ivTranferStatus;
    private AnimationDrawable animationDrawable;


    private String transferTime;
    private TextView tvTime;
    private TextView tvTimeValue;
    private SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    private SimpleDateFormat sf1 = new SimpleDateFormat("yyyyMMddHHmmss");
    private EthTokenTransactionManager transactionManager;


    private Account account;
    //收款地址
    private String receiveAddress;
    //付款地址
    private String payAddress;
    //合约地址
    private String contractAddress;
    //转账金额
    private String amount;
    //矿工费
    private String gasPrice1;
    //聊天人的id
    private String toUserId;
    //是否发送消息
    private boolean doSendMsg = false;
    private AssetListBean assetListBean;
    private int chainId;
    private Disposable disposable;
    private String convertGas;



    public static void start(Context context, String receiveAddress, String payAddress,
                             String amount, String gasPrice1,String convertGas, int chainId, AssetListBean assetListBean,
                             String toUserId, int accountType) {
        Intent starter = new Intent(context, ChatTransferSuccessActivity.class);
        starter.putExtra("receiveAddress", receiveAddress);
        starter.putExtra("payAddress", payAddress);
        starter.putExtra("amount", amount);
        starter.putExtra("gasPrice1", gasPrice1);
        starter.putExtra("chainId", chainId);
        starter.putExtra("toUserId", toUserId);
        starter.putExtra("accountType", accountType);
        //转换后后的手续费只用于显示！
        starter.putExtra("convertGas", convertGas);
        if (assetListBean != null) {
            starter.putExtra("assetListBean", assetListBean);
        }


        context.startActivity(starter);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.talk_chain_activity_transfer_success);

        receiveAddress = getIntent().getStringExtra("receiveAddress");
        payAddress = getIntent().getStringExtra("payAddress");
        amount = getIntent().getStringExtra("amount");
        gasPrice1 = getIntent().getStringExtra("gasPrice1");
        convertGas = getIntent().getStringExtra("convertGas");
        chainId = getIntent().getIntExtra("chainId", chainId);

        account = new AccountDao(this).getAccount(payAddress);
        if (getIntent().getSerializableExtra("assetListBean") != null) {
            assetListBean = (AssetListBean) getIntent().getSerializableExtra("assetListBean");
            contractAddress = assetListBean.getAddress();

        }
        if (getIntent().getStringExtra("toUserId") != null) {
            toUserId = getIntent().getStringExtra("toUserId");
            doSendMsg = true;
        }

        initView();
        int accountType = getIntent().getIntExtra("accountType", 0);
        if (accountType == 2 && chainId != EosNetParamUtil.getEosChainId()) {
            //冷钱包，连接蓝牙读卡器
            //todo eos暂不支持冷钱包
            Intent intent;
            //支持自带nfc读写
            if (!EnvSupportManager.isSupportNfcWallet() && !EnvSupportManager.isSupportForceBleNfc()) {
                return;
            }
            if (!EnvSupportManager.isSupportForceBleNfc() && Common.hasMifareClassicSupport(this)) {
                intent = new Intent(this, MifareNfcMessageActivity.class);
            } else {
                //蓝牙读卡器
                intent = new Intent(this, BleBlutoothScanActivity.class);
                intent.putExtra("bleDeviceType", BleBlutoothScanActivity.BLE_TYPE_NFC);
            }
            intent.putExtra("address", payAddress);
            intent.putExtra("createType", BleBlutoothScanActivity.TYPE_READ_PRIV_KEY);
            startActivityForResult(intent, REQUEST_READ_NFC_PRIV_KEY);
            return;
        }
        if (chainId == IPAssetsConstant.CHAIN_ID_BTC) {
            if (EnvSupportManager.isSupportHDWallet() && !StringUtils.isEmpty(account.getHdBtcCurrentChildAddress())) {
                startBtcTransfer(TCAccountManager
                        .decryptByMainPrivKey(account.getSecretMnemonic()));
            } else {
                startBtcTransfer(account.getFileName());
            }
        }else if (chainId == IPAssetsConstant.CHAIN_ID_ETH){
            startEthTransfer();
        } else if (chainId == IPAssetsConstant.CHAIN_ID_EOS){
            startEosTransfer();
        }
    }

    private void startEthTransfer() {
        transactionManager = new EthTokenTransactionManager(this);
        transactionManager.loadCredentialsASync(account,
                new EthTokenTransactionManager.LoadCredentialsCallBack() {
                    @Override
                    public void loadResult(boolean isSuccess, final Credentials credentials) {
                        ethCredentialTx(isSuccess, credentials);
                    }
                });
    }

    private void ethCredentialTx(boolean isSuccess, final Credentials credentials) {
        if (!isSuccess) {
            onFailAnim();
            return;
        }
        //2.获取nonce
//                        LogUtils.i("获取nonce", credentials.getAddress());
        transactionManager.getTransactionNonce(payAddress,chainId, new EthTokenTransactionManager.NonceCallBack() {
            @Override
            public void nonceResult(boolean isSuccess, BigInteger nonce) {
                if (!isSuccess) {
                    onFailAnim();
                    return;
                }
                //3.开始转账
//                                LogUtils.i("开始转账", nonce);
                //普通转账
                if (assetListBean == null) {
                    transactionManager.startEthTransaction(nonce, payAddress,
                            EnvironmentVariable.getProperty(Constants.CHAT_USER_ID),
                            receiveAddress, toUserId,
                            Convert.toWei(amount, Convert.Unit.ETHER).toBigInteger(),
                            credentials, EthTokenTransactionManager.ETH_COIN_CHAINID,
//                            Convert.toWei(gasPrice1, Convert.Unit.ETHER).toBigInteger().divide(Contract.GAS_LIMIT),
                            Convert.toWei(gasPrice1, Convert.Unit.GWEI).toBigInteger(),
                            Contract.GAS_LIMIT, new EthTokenTransactionManager.TransactionCallBack<String>() {
                                @Override
                                public void transactionResult(boolean isSuccess, String result) {
                                    if (!isSuccess) {
                                        //showTransactionResult(false, ResStringUtil.getString(R.string.open_planet_transaction_fail));
                                        // showTransactionResult(true, result);
                                        onFailAnim();
                                        return;
                                    }
                                    //转账成功
                                    // TODO: 18-6-14
                                    try {
                                        showTransactionResult(true, result);
                                    } catch (Exception e) {
                                        e.printStackTrace();
                                    }

                                }
                            });
                } else {
                    //智能合约转账
                    //矿工费
//                    BigInteger gasPrice = Convert.toWei(gasPrice1, Convert.Unit.ETHER).toBigInteger().divide(Contract.GAS_LIMIT);
                    BigInteger gasPrice = Convert.toWei(gasPrice1, Convert.Unit.GWEI).toBigInteger();
                    LogUtils.d("GAS:" + gasPrice.toString());

                    transactionManager.startEthTokenTransaction(nonce, payAddress,
                            EnvironmentVariable.getProperty(Constants.CHAT_USER_ID),
                            receiveAddress, "",
                            new BigDecimal(amount).multiply(BigDecimal.TEN.pow(assetListBean.getTokenDecimals())).toBigInteger(),
                            amount, credentials, gasPrice,
                            contractAddress,
                            Byte.valueOf(assetListBean.getBlockChainID()), assetListBean.getId(),
                            assetListBean.getName(), new EthTokenTransactionManager.TransactionCallBack<String>() {
                                @Override
                                public void transactionResult(boolean isSuccess, String result) {
                                    if (!isSuccess) {
                                        // showTransactionResult(false, ResStringUtil.getString(R.string.open_planet_transaction_fail));
                                        onFailAnim();
                                        // showTransactionResult(true, result);
                                        return;
                                    }
                                    //转账成功
                                    showTransactionResult(true, result);
                                }
                            });
                }
            }
        });
    }

    private void startEosTransfer() {
        disposable = Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> emitter) throws Exception {
                EosAccountGenerator eosAccountGenerator = new EosAccountGenerator(ChatTransferSuccessActivity.this);
                //获取链上的信息
                EosChainInfo eosChainInfo = eosAccountGenerator.getChainInfo(TAG);
                //组织数据，得到transaction tx
                SignedTransaction tx = eosAccountGenerator.parseTransferData(payAddress,
                        receiveAddress, amount + (chainId == IPAssetsConstant.CHAIN_ID_EOS ?
                " EOS" : " SYS"), "", eosChainInfo);
                //对tx签名，返回tx的toString json格式
                String packedTx = eosAccountGenerator.signTransaction(payAddress, tx,
                        new TypeChainId(eosChainInfo.getChain_id()));
                //push transaction, 返回交易id
                String txId = eosAccountGenerator.pushTransaction(TAG, packedTx);
                emitter.onNext(txId);
                emitter.onComplete();
            }
        })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<String>() {
                    @Override
                    public void accept(String s) throws Exception {
                        TCLoadingDataView.dismiss();
                        if (s != null) {
                            showEosTransactionResult( s);
                        } else {
                            onFailAnim( );
                        }
                    }
                }, new Consumer<Throwable>() {
                    @Override
                    public void accept(Throwable throwable) throws Exception {
                        onFailAnim( );
                    }
                });
    }

    private void startBtcTransfer(String pathOrMnemonics) {
        AccountDao accountDao = new AccountDao(this);
        Account account = accountDao.getAccount(payAddress);
        boolean isHdWallet = EnvSupportManager.isSupportHDWallet() && !StringUtils.isEmpty(account.getHdBtcCurrentChildAddress());
        new UTXOTransactionManager().getUTXO(this, TAG, payAddress, pathOrMnemonics, receiveAddress, Coin.valueOf(BalanceUtil.btcToBiInteger(amount).longValue()),
                Coin.valueOf(3000),
                isHdWallet,
                new UTXOTransactionManager.OnTransactionListener() {
                    @Override
                    public void onTxSuccess(Transaction tx) {
                        showBtcTransactionResult(tx);
                    }

                    @Override
                    public void onTxFail(String e) {
                        onFailAnim();
                    }
                });
    }

    /**
     * pwr，eth等转账结果
     * @param isSucess 是否成功
     * @param result 转账返回的结果
     */
    private void showTransactionResult(boolean isSucess, String result) {
        JSONObject jsonObject = null;
        try {
            jsonObject = JSONObject.fromObject(result);
        } catch (Exception e) {
            e.printStackTrace();
            jsonObject = new JSONObject();
        }
        animationDrawable.stop();
        ivTranferStatus.setBackground(null);
        ivTranferStatus.setImageDrawable(ContextCompat.getDrawable(ChatTransferSuccessActivity.this, R.drawable.transfer_success));
        tvCount.setText("-" + amount);
        tvCount.setVisibility(View.VISIBLE);
        tvTransStatus.setText(ResStringUtil.getString(R.string.open_planet_transfer_success));
        tvCountUnit.setVisibility(View.VISIBLE);
        tvCodeIntro.setVisibility(View.VISIBLE);
        tvCode.setVisibility(View.VISIBLE);
        tvCode.setText(jsonObject.optString("transactionHash", ""));
        tvMyAddress.setVisibility(View.VISIBLE);
        tvToAddress.setVisibility(View.VISIBLE);
        tvMyAddressIntro.setVisibility(View.VISIBLE);
        tvToAddressIntro.setVisibility(View.VISIBLE);

        tvTime.setVisibility(View.VISIBLE);
        tvTimeValue.setVisibility(View.VISIBLE);

        try {

            Date date = sf1.parse(jsonObject.optString("time", sf1.format(new Date())));
            transferTime = sf.format(date);
            tvTimeValue.setText(transferTime);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (doSendMsg) {
            sendTransferMsg();
            finish();
        }
    }

    /**
     * 处理btc转账结果
     */
    private void showBtcTransactionResult(Transaction tx) {
        animationDrawable.stop();
        ivTranferStatus.setBackground(null);
        ivTranferStatus.setImageDrawable(ContextCompat.getDrawable(ChatTransferSuccessActivity.this, R.drawable.transfer_success));
        tvCount.setText("-" + amount);
        tvCount.setVisibility(View.VISIBLE);
        tvTransStatus.setText(ResStringUtil.getString(R.string.open_planet_transfer_success));
        tvCountUnit.setVisibility(View.VISIBLE);
        tvCodeIntro.setVisibility(View.VISIBLE);
        tvCode.setVisibility(View.VISIBLE);
        tvCode.setText(tx.getHashAsString());
        tvMyAddress.setVisibility(View.VISIBLE);
        tvToAddress.setVisibility(View.VISIBLE);
        tvMyAddressIntro.setVisibility(View.VISIBLE);
        tvToAddressIntro.setVisibility(View.VISIBLE);

        tvTime.setVisibility(View.VISIBLE);
        tvTimeValue.setVisibility(View.VISIBLE);

        try {
            transferTime = sf.format(new Date());
            tvTimeValue.setText(transferTime);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (doSendMsg) {
            sendTransferMsg();
            finish();
        }
    }

    /**
     * 处理btc转账结果
     */
    private void showEosTransactionResult(String txHash) {
        animationDrawable.stop();
        ivTranferStatus.setBackground(null);
        ivTranferStatus.setImageDrawable(ContextCompat.getDrawable(ChatTransferSuccessActivity.this, R.drawable.transfer_success));
        tvCount.setText("-" + amount);
        tvCount.setVisibility(View.VISIBLE);
        tvTransStatus.setText(ResStringUtil.getString(R.string.open_planet_transfer_success));
        tvCountUnit.setVisibility(View.VISIBLE);
        tvCodeIntro.setVisibility(View.VISIBLE);
        tvCode.setVisibility(View.VISIBLE);
        tvCode.setText(txHash);
        tvMyAddress.setVisibility(View.VISIBLE);
        tvToAddress.setVisibility(View.VISIBLE);
        tvMyAddressIntro.setVisibility(View.VISIBLE);
        tvToAddressIntro.setVisibility(View.VISIBLE);

        tvTime.setVisibility(View.VISIBLE);
        tvTimeValue.setVisibility(View.VISIBLE);

        try {
            transferTime = sf.format(new Date());
            tvTimeValue.setText(transferTime);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (doSendMsg) {
            sendTransferMsg();
            finish();
        }
    }


    @Override
    protected void onStop() {
        super.onStop();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        dispose();
        if (transactionManager!=null) transactionManager.dispose();
    }

    private void initView() {
        ImageView ivBack = (ImageView) findViewById(R.id.iv_back);
        ivBack.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                finish();
            }
        });
        ivTranferStatus = (ImageView) findViewById(R.id.transfer_anim);
//        Bitmap bitmap = ((BitmapDrawable) ivTranferStatus.getBackground()).getBitmap();
        animationDrawable = (AnimationDrawable) ivTranferStatus.getBackground();
        animationDrawable.start();
        tvTitle = (TextView) findViewById(R.id.tv_title);
        tvTitle.setText(ResStringUtil.getString(R.string.open_planet_transfer_detail));
        tvCode = (TextView) findViewById(R.id.tv_transfer_code);
        tvCode.setText("");
        tvCodeIntro = (TextView) findViewById(R.id.tv_transaction_no);
        tvMyAddress = (TextView) findViewById(R.id.tv_sell_account);
        tvMyAddress.setText(payAddress);
        tvToAddress = (TextView) findViewById(R.id.tv_buy_account);
        tvToAddress.setText(receiveAddress);
        tvMyAddressIntro = (TextView) findViewById(R.id.tv_sell_account_intro);
        tvToAddressIntro = (TextView) findViewById(R.id.tv_buy_account_intro);
        tvCount = (TextView) findViewById(R.id.tv_count);
        tvCountUnit = (TextView) findViewById(R.id.tv_count_unit);
        tvTransStatus = (TextView) findViewById(R.id.tv_welcome);
        tvTransStatus.setText(ResStringUtil.getString(R.string.open_planet_transferring));

        tvTime = (TextView) findViewById(R.id.tv_transtime);
        tvTimeValue = (TextView) findViewById(R.id.tv_transtime_value);

    }

    //转账失败
    private void onFailAnim() {
        animationDrawable.stop();
        ivTranferStatus.setBackground(null);
        ivTranferStatus.setImageDrawable(ContextCompat.getDrawable(ChatTransferSuccessActivity.this, R.drawable.transfer_fail));
        tvCodeIntro.setVisibility(View.GONE);
        tvCode.setText("");
        tvTransStatus.setVisibility(View.VISIBLE);
        tvTransStatus.setText(ResStringUtil.getString(R.string.open_planet_transaction_fail));
        tvMyAddress.setVisibility(View.VISIBLE);
        tvToAddress.setVisibility(View.VISIBLE);
        tvMyAddressIntro.setVisibility(View.VISIBLE);
        tvToAddressIntro.setVisibility(View.VISIBLE);
    }

    //发送消息
    private void sendTransferMsg() {
        //    @"{\"receiveUserId\":\"接收方账户（手机号）\",\"receiveWalletAddress\":\"接收方钱包地址\",
        // \"receiveIMUserId\":\"接收方账户（星际ID）\",\"sendUserId\":\"发送方账户\",\"sendWalletAddress\":\"发送方钱包地址\",
        // \"sendIMUserId\":\"发送方账户（星际ID）\",\"money\":\"能量\",\"tradingTime\":\"交易时间s\",\"tradingID\":\"交易ID\"}"

        long currenttime = new Date().getTime();
        Map<String, Object> map = new HashMap<>();
        map.put("receiveUserId", toUserId);
        map.put("receiveWalletAddress", receiveAddress);
        map.put("sendUserId", EnvironmentVariable.getUserName());
        map.put("sendWalletAddress", payAddress);
        map.put("money", amount);
        map.put("tradingTime", transferTime);
        map.put("sendIMUserId", EnvironmentVariable.getProperty(CHAT_USER_ID));
        map.put("receiveIMUserId", toUserId);
        map.put("tradingID", tvCode.getText().toString());

        //货币单位
        if (chainId == IPAssetsConstant.CHAIN_ID_ETH) {
            map.put("moneyUnit", assetListBean == null ? "ETH" : assetListBean.getName());
        } else if (chainId == IPAssetsConstant.CHAIN_ID_BTC) {
            map.put("moneyUnit", "BTC");

        } else if (chainId == IPAssetsConstant.CHAIN_ID_EOS) {
            map.put("moneyUnit", "EOS");
        } else if (chainId == IPAssetsConstant.CHAIN_ID_EOSTEST) {
            map.put("moneyUnit", "SYS");
        }
        map.put("chainId", chainId);
        org.json.JSONObject jsonObject = new org.json.JSONObject(map);
        IMStruct002 imStruct002 = new IMStruct002();
        try {
            imStruct002.setBody(jsonObject.toString().getBytes("UTF-8"));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        imStruct002.setTime(currenttime);
        imStruct002.setToUserType(StructFactory.TO_USER_TYPE_PERSONAL);
        imStruct002.setToUserId(Integer.valueOf(toUserId));
        imStruct002.setFromUserId(Integer.valueOf(EnvironmentVariable.getProperty(CHAT_USER_ID)));
        imStruct002.setMessageChildType((short) 8);
        JFMessageManager.getInstance().sendMessage(imStruct002);
        finish();
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQUEST_READ_NFC_PRIV_KEY) {
            if (resultCode == RESULT_OK) {
                String privKey = data.getStringExtra("privateKey");
                if (chainId == IPAssetsConstant.CHAIN_ID_ETH || chainId == IPAssetsConstant.CHAIN_ID_TURBOCHAIN) {
                    startEthTxByPrivKey(privKey);
                } else if (chainId == IPAssetsConstant.CHAIN_ID_BTC) {
                    startBtcTransfer(privKey);
                } else if (chainId == EosNetParamUtil.getEosChainId()) {
                    //todo
                }

            } else {
                onTxFail();
            }
        }
    }

    /**
     * 使用私钥交易
     * @param privKey 私钥
     */
    private void startEthTxByPrivKey(String privKey) {
        transactionManager = new EthTokenTransactionManager(this);
        Account account = new AccountDao(this).getAccount(payAddress);
        if (account != null) {
            transactionManager.loadCredentialsByPrvkeyASync(privKey, new EthTokenTransactionManager.LoadCredentialsCallBack() {
                @Override
                public void loadResult(boolean isSuccess, Credentials credentials) {
                    ethCredentialTx(isSuccess, credentials);
                }
            });
        }
    }

    private void onTxFail() {
        onFailAnim();
    }
}
